#!/usr/bin/python

import socket
import argparse
import struct
import messages
import os
import packet_queue

IN_BUFFER_SIZE = 2048

parser = argparse.ArgumentParser(description="Get a file.")
parser.add_argument('-n','--hostname',type=str, default = '127.0.0.1',
                    help='remote hostname')
parser.add_argument('filename',type=str,
                    help='filename to get from server')
parser.add_argument('-r','--rate', type=int, default=65535,
                    help='byte rate in bytes/second')
parser.add_argument('-s','--packet_size',type=int, default=1024,
                    help='packet size in bytes')
parser.add_argument('-p','--port',type=int, default=5005,
                    help='remote port')        
parser.add_argument('-l','--local_port',type=int, default=5006,
                    help='local port')                      
                    
args = parser.parse_args()


    
get_file_message = messages.GetFileMessage(args.filename,
                                  args.rate,
                                  args.packet_size)
                                  
print "UDP target IP:", args.hostname
print "UDP target port:", args.port
print "message:", get_file_message

sock = socket.socket(socket.AF_INET, # Internet
                     socket.SOCK_DGRAM) # UDP

#sock_in = socket.socket(socket.AF_INET, # Internet
#                     socket.SOCK_DGRAM) # UDP

sock.bind(('', args.local_port))

sock.sendto(get_file_message.pack(), (args.hostname, args.port))
sock.settimeout(5)
local_port = sock.getsockname()[1]

print local_port



 



class DataCache:
  def __init__(self,packet_size):
    self.packet_size = packet_size
    self.num_packets = None
    self.data = []
    self.queue = []
    
  def append_message(self,message):
    if not self.num_packets: 
      self.num_packets = message.num_packets
      self.queue = packet_queue.Queue(self.num_packets,0)
    elif self.num_packets != message.num_packets:
      print self.num_packets, message.num_packets
      print "error differening num_packets"
      
    self.data.insert(message.packet_id, message.data)
    self.queue[message.packet_id] = 1
    
  def assemble(self):
    data_assemble = ''
    for packet in self.data:
      data_assemble += packet
    return data_assemble
  
  def all_packets_received(self):
    if not self.num_packets:
      return False
    return self.queue.all_packets_received()

      

data_cache = DataCache(args.packet_size)

while not data_cache.all_packets_received():
  try:
    data, addr = sock.recvfrom(IN_BUFFER_SIZE) 
    message = messages.SendPacketMessage()
    message.unpack(data)
    print chr(27) + "[2J"
    print message
    data_cache.append_message(message)
    print data_cache.queue
  except (KeyboardInterrupt, SystemExit):
    raise
  except Exception as e:
    print e
    packets_message = messages.GetPacketsMessage(data_cache.queue.get_inverse())
    sock.sendto(packets_message.pack(), (args.hostname, args.port))
    print 'sending request packets message: ', packets_message

  
data = data_cache.assemble()
filename_out = os.path.basename(args.filename) + '.in'
with open(filename_out,'w') as f:
  f.write(data)
  